package com.web.crawler.k_means;

import com.web.crawler.compare.DocumentComparator;
import com.web.crawler.compare.SimilarityCalculator;

import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;

public class ClusteringAnalyzer {
    private DocumentComparator comparator;
    private List<double[]> tfIdfVectors;

    public ClusteringAnalyzer(String folderPath) throws IOException {
        this.comparator = new DocumentComparator(folderPath);
        this.tfIdfVectors = comparator.getTfIdfVectors();
    }

    public void  analyze(int[] kValues) {
        for (int k : kValues) {
            System.out.println("\n====================================");
            System.out.println("Clustering into " + k + " clusters");
            System.out.println("====================================");

            // 参数1：k值，参数2：最大迭代次数，参数3：TF-IDF，参数4：文档名称，参数5：文档内容
            KMeansClusterer clusterer = new KMeansClusterer(
                    k, 100, tfIdfVectors,
                    comparator.getDocumentNames(),
                    comparator.getDocumentContents());

            List<Cluster> clusters = clusterer.cluster();

            // 按聚类大小排序
            clusters.sort((c1, c2) -> Integer.compare(
                    c2.getMembers().size(), c1.getMembers().size()));

            // 显示前3大聚类
            System.out.println("\nTop 3 largest clusters:");
            for (int i = 0; i < Math.min(3, clusters.size()); i++) {
                printClusterInfo(clusters.get(i), i+1);
            }

            // 计算聚类质量指标
            double sse = calculateSSE(clusters);
            System.out.printf("\nSum of Squared Errors (SSE): %.2f\n", sse);
        }
    }

    private void printClusterInfo(Cluster cluster, int rank) {
        System.out.println("\nCluster #" + rank);
        System.out.println("Size: " + cluster.getMembers().size());
        System.out.println("Representative documents (closest to centroid):");

        for (int docIndex : cluster.getRepresentativeDocuments()) {
            String docName = comparator.getDocumentNames().get(docIndex);
            String preview = comparator.getDocumentContents().get(docIndex)
                    .substring(0, Math.min(100, comparator.getDocumentContents().get(docIndex).length()));

            System.out.println("- " + docName);
            System.out.println("  Preview: " + preview.replace("\n", " ") + "...");
        }
    }

    private double calculateSSE(List<Cluster> clusters) {
        double sse = 0.0;

        for (Cluster cluster : clusters) {
            for (int memberIndex : cluster.getMembers()) {
                double distance = SimilarityCalculator.cosineDistance(
                        tfIdfVectors.get(memberIndex), cluster.getCentroid());
                sse += distance * distance;
            }
        }

        return sse;
    }
}